// Reese's Keyboard.c
// CS 38033 - Spring 2004
// Lab 4
// Part 2
//
// Keyboard.c

typedef int			BOOL;
typedef unsigned char		BYTE8;
typedef unsigned short int	WORD16;
typedef unsigned long int	DWORD32;
#define	PRIVATE	static

#ifndef TRUE
#define	TRUE		1
#endif
#ifndef FALSE
#define	FALSE		0
#endif

#define	ENTRIES(a)	(sizeof(a)/sizeof(a[0]))



extern unsigned short currentRow;
extern unsigned short currentCol;


typedef struct STATE
	{
	BOOL	ins;
	BOOL	rshift;
	BOOL	lshift;
	BOOL	alt;
	BOOL	ctrl;
	BOOL	caps;
	BOOL	scrl;
	BOOL	num;
	} __attribute__((packed)) STATE;

#define	KYBD_STS_PORT	0x64
#define	KYBD_DAT_PORT	0x60
#define	KYBD_DAT_RDY	0x01
#define	BREAK_CODE	0x80
#define	SIZE	20
#define false 	0
#define true 	1

char buffer[16];

unsigned char inportb(unsigned short port);


PRIVATE STATE state; /* Initialized to all FALSE by loader */

//PRIVATE BYTE8		scan_codes[SIZE];
//PRIVATE unsigned int	nq = 0;
//PRIVATE unsigned int	dq = 0;
//PRIVATE unsigned int	count = 0;

/* -------------------------------------------------------------------- */
/* Scan code translation table.						*/
/* The incoming scan code from the keyboard selects a row.		*/
/* The modifier status selects the column.				*/
/* The word at the intersection of the two is the scan/ASCII code 	*/
/* -------------------------------------------------------------------- */
PRIVATE WORD16 scan_ascii[][8] = {
/*      norm,    shft,   ctrl,   alt,    num,    caps,   shcap,  shnum */
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*ESC*/	{0x011B, 0x011B, 0x011B, 0x011B, 0x011B, 0x011B, 0x011B, 0x011B},
/*1 !*/	{0x0231, 0x0221, 0x0000, 0x7800, 0x0231, 0x0231, 0x0231, 0x0321},
/*2 @*/	{0x0332, 0x0340, 0x0300, 0x7900, 0x0332, 0x0332, 0x0332, 0x0332},
/*3 #*/	{0x0433, 0x0423, 0x0000, 0x7A00, 0x0433, 0x0433, 0x0423, 0x0423},
/*4 $*/	{0x0534, 0x0524, 0x0000, 0x7B00, 0x0534, 0x0534, 0x0524, 0x0524},
/*5 %*/	{0x0635, 0x0625, 0x0000, 0x7C00, 0x0635, 0x0635, 0x0625, 0x0625},
/*6 ^*/	{0x0736, 0x075E, 0x071E, 0x7D00, 0x0736, 0x0736, 0x075E, 0x075E},
/*7 &*/	{0x0837, 0x0826, 0x0000, 0x7E00, 0x0837, 0x0837, 0x0826, 0x0826},
/*8 **/	{0x0938, 0x092A, 0x0000, 0x7F00, 0x0938, 0x0938, 0x092A, 0x092A},
/*9 (*/	{0x0A39, 0x0A28, 0x0000, 0x8000, 0x0A39, 0x0A39, 0x0A28, 0x0A28},
/*0 )*/	{0x0B30, 0x0B29, 0x0000, 0x8100, 0x0B30, 0x0B30, 0x0B29, 0x0B29},
/*- _*/	{0x0C2D, 0x0C5F, 0x0000, 0x8200, 0x0C2D, 0x0C2D, 0x0C5F, 0x0C5F},
/*= +*/	{0x0D3D, 0x0D2B, 0x0000, 0x8300, 0x0D3D, 0x0D3D, 0x0D2B, 0x0D2B},
/*bksp*/{0x0E08, 0x0E08, 0x0E7F, 0x0000, 0x0E08, 0x0E08, 0x0E08, 0x0E08},
/*Tab*/	{0x0F09, 0x0F00, 0x0000, 0x0000, 0x0F09, 0x0F09, 0x0F00, 0x0F00},
/*Q*/	{0x1071, 0x1051, 0x1011, 0x1000, 0x1071, 0x1051, 0x1051, 0x1071},
/*W*/	{0x1177, 0x1057, 0x1017, 0x1100, 0x1077, 0x1057, 0x1057, 0x1077},
/*E*/	{0x1265, 0x1245, 0x1205, 0x1200, 0x1265, 0x1245, 0x1245, 0x1265},
/*R*/	{0x1372, 0x1352, 0x1312, 0x1300, 0x1272, 0x1252, 0x1252, 0x1272},
/*T*/	{0x1474, 0x1454, 0x1414, 0x1400, 0x1474, 0x1454, 0x1454, 0x1474},
/*Y*/	{0x1579, 0x1559, 0x1519, 0x1500, 0x1579, 0x1559, 0x1579, 0x1559},
/*U*/	{0x1675, 0x1655, 0x1615, 0x1600, 0x1675, 0x1655, 0x1675, 0x1655},
/*I*/	{0x1769, 0x1749, 0x1709, 0x1700, 0x1769, 0x1749, 0x1769, 0x1749},
/*O*/	{0x186F, 0x184F, 0x180F, 0x1800, 0x186F, 0x184F, 0x186F, 0x184F},
/*P*/	{0x1970, 0x1950, 0x1910, 0x1900, 0x1970, 0x1950, 0x1970, 0x1950},
/*[ {*/	{0x1A5B, 0x1A7B, 0x1A1B, 0x0000, 0x1A5B, 0x1A5B, 0x1A7B, 0x1A7B},
/*] }*/	{0x1B5D, 0x1B7D, 0x1B1D, 0x0000, 0x1B5D, 0x1B5D, 0x1B7D, 0x1B7D},
/*entr*/{0x1C0D, 0x1C0D, 0x1C0A, 0x0000, 0x1C0D, 0x1C0D, 0x1C0A, 0x1C0A},
/*ctrl*/{0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00, 0x1D00},
/*A*/   {0x1E61, 0x1E41, 0x1E01, 0x1E00, 0x1E61, 0x1E41, 0x1E61, 0x1E41},
/*S*/	{0x1F73, 0x1F53, 0x1F13, 0x1F00, 0x1F73, 0x1F53, 0x1F73, 0x1F53},
/*D*/	{0x2064, 0x2044, 0x2004, 0x2000, 0x2064, 0x2044, 0x2064, 0x2044},
/*F*/	{0x2166, 0x2146, 0x2106, 0x2100, 0x2166, 0x2146, 0x2166, 0x2146},
/*G*/	{0x2267, 0x2247, 0x2207, 0x2200, 0x2267, 0x2247, 0x2267, 0x2247},
/*H*/	{0x2368, 0x2348, 0x2308, 0x2300, 0x2368, 0x2348, 0x2368, 0x2348},
/*J*/	{0x246A, 0x244A, 0x240A, 0x2400, 0x246A, 0x244A, 0x246A, 0x244A},
/*K*/	{0x256B, 0x254B, 0x250B, 0x2500, 0x256B, 0x254B, 0x256B, 0x254B},
/*L*/	{0x266C, 0x264C, 0x260C, 0x2600, 0x266C, 0x264C, 0x266C, 0x264C},
/*; :*/	{0x273B, 0x273A, 0x0000, 0x0000, 0x273B, 0x273B, 0x273A, 0x273A},
/*' "*/	{0x2827, 0x2822, 0x0000, 0x0000, 0x2827, 0x2827, 0x2822, 0x2822},
/*` ~*/	{0x2960, 0x297E, 0x0000, 0x0000, 0x2960, 0x2960, 0x297E, 0x297E},
/*LShf*/{0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00, 0x2A00},
/*\ |*/	{0x2B5C, 0x2B7C, 0x2B1C, 0x0000, 0x2B5C, 0x2B5C, 0x2B7C, 0x2B7C},
/*Z*/	{0x2C7A, 0x2C5A, 0x2C1A, 0x2C00, 0x2C7A, 0x2C5A, 0x2C7A, 0x2C5A},
/*X*/	{0x2D78, 0x2D58, 0x2D18, 0x2D00, 0x2D78, 0x2D58, 0x2D78, 0x2D58},
/*C*/	{0x2E63, 0x2E43, 0x2E03, 0x2E00, 0x2E63, 0x2E43, 0x2E63, 0x2E43},
/*V*/	{0x2F76, 0x2F56, 0x2F16, 0x2F00, 0x2F76, 0x2F56, 0x2F76, 0x2F56},
/*B*/	{0x3062, 0x3042, 0x3002, 0x3000, 0x3062, 0x3042, 0x3062, 0x3042},
/*N*/	{0x316E, 0x314E, 0x310E, 0x3100, 0x316E, 0x314E, 0x316E, 0x314E},
/*M*/	{0x326D, 0x324D, 0x320D, 0x3200, 0x326D, 0x324D, 0x326D, 0x324D},
/*, <*/	{0x332C, 0x333C, 0x0000, 0x0000, 0x332C, 0x332C, 0x333C, 0x333C},
/*. >*/	{0x342E, 0x343E, 0x0000, 0x0000, 0x342E, 0x342E, 0x343E, 0x343E},
/*/ ?*/	{0x352F, 0x353F, 0x0000, 0x0000, 0x352F, 0x352F, 0x353F, 0x353F},
/*rshf*/{0x3600, 0x3600, 0x3600, 0x3600, 0x3600, 0x3600, 0x3600, 0x3600},
/** PS*/{0x372A, 0x0000, 0x3710, 0x0000, 0x372A, 0x372A, 0x0000, 0x0000},
/*alt*/	{0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800, 0x3800},
/*spc*/	{0x3920, 0x3920, 0x3920, 0x0000, 0x3920, 0x3920, 0x3920, 0x3920},
/*caps*/{0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00, 0x3A00},
/*F1*/	{0x3B00, 0x5400, 0x5E00, 0x6800, 0x3B00, 0x3B00, 0x5400, 0x5400},
/*F2*/	{0x3C00, 0x5500, 0x5F00, 0x6900, 0x3C00, 0x3C00, 0x5500, 0x5500},
/*F3*/	{0x3D00, 0x5600, 0x6000, 0x6A00, 0x3D00, 0x3D00, 0x5600, 0x5600},
/*F4*/	{0x3E00, 0x5700, 0x6100, 0x6B00, 0x3E00, 0x3E00, 0x5700, 0x5700},
/*F5*/	{0x3F00, 0x5800, 0x6200, 0x6C00, 0x3F00, 0x3F00, 0x5800, 0x5800},
/*F6*/	{0x4000, 0x5900, 0x6300, 0x6D00, 0x4000, 0x4000, 0x5900, 0x5900},
/*F7*/	{0x4100, 0x5A00, 0x6400, 0x6E00, 0x4100, 0x4100, 0x5A00, 0x5A00},
/*F8*/	{0x4200, 0x5B00, 0x6500, 0x6F00, 0x4200, 0x4200, 0x5B00, 0x5B00},
/*F9*/	{0x4300, 0x5C00, 0x6600, 0x7000, 0x4300, 0x4300, 0x5C00, 0x5C00},
/*F10*/	{0x4400, 0x5D00, 0x6700, 0x7100, 0x4400, 0x4400, 0x5D00, 0x5D00},
/*num*/	{0x4500, 0x4500, 0x4500, 0x4500, 0x4500, 0x4500, 0x4500, 0x4500},
/*scrl*/{0x4600, 0x4600, 0x4600, 0x4600, 0x4600, 0x4600, 0x4600, 0x4600},
/*home*/{0x4700, 0x4737, 0x7700, 0x0000, 0x4737, 0x4700, 0x4737, 0x4700},
/*up*/	{0x4800, 0x4838, 0x0000, 0x0000, 0x4838, 0x4800, 0x4838, 0x4800},
/*pgup*/{0x4900, 0x4939, 0x8400, 0x0000, 0x4939, 0x4900, 0x4939, 0x4900},
/*-*/	{0x4A2D, 0x4A2D, 0x0000, 0x0000, 0x4A2D, 0x4A2D, 0x4A2D, 0x4A2D},
/*left*/{0x4B00, 0x4B34, 0x7300, 0x0000, 0x4B34, 0x4B00, 0x4B34, 0x4B00},
/*Cntr*/{0x4C00, 0x4C35, 0x0000, 0x0000, 0x4C35, 0x4C00, 0x4C35, 0x4C00},
/*rght*/{0x4D00, 0x4D36, 0x7400, 0x0000, 0x4D36, 0x4D00, 0x4D36, 0x4D00},
/*+*/	{0x4E2B, 0x4E2B, 0x0000, 0x0000, 0x4E2B, 0x4E2B, 0x4E2B, 0x4E2B},
/*end*/	{0x4F00, 0x4F31, 0x7500, 0x0000, 0x4F31, 0x4F00, 0x4F31, 0x4F00},
/*down*/{0x5000, 0x5032, 0x0000, 0x0000, 0x5032, 0x5000, 0x5032, 0x5000},
/*pgdn*/{0x5100, 0x5133, 0x7600, 0x0000, 0x5133, 0x5100, 0x5133, 0x5100},
/*ins*/	{0x5200, 0x5230, 0x0000, 0x0000, 0x5230, 0x5200, 0x5230, 0x5200},
/*del*/	{0x5300, 0x532E, 0x0000, 0x0000, 0x532E, 0x5300, 0x532E, 0x5300},
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*--*/	{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
/*F11*/	{0x5700, 0x0000, 0x0000, 0x0000, 0x5700, 0x5700, 0x0000, 0x0000},
/*F12*/	{0x5800, 0x0000, 0x0000, 0x0000, 0x5800, 0x5800, 0x0000, 0x0000}
};

/* ------------------------------------------------------------ */
/* Functions ...						*/
/* ------------------------------------------------------------ */

char * uitoa(unsigned n, char *s, int radix) { 
	static const char tab[] =
		"0123456789abcdef"; 
	char *p = s;
	char *q = s;

/* generate digits in reverse order */ 
	do { 
		*p++ = tab[n % radix];
		n /= radix; 
	} while (n != 0);

	*p-- = '\0';

/* reverse digits */ 
	while (q < p) { 
		int temp = *p; 
		*p-- = *q; 
		*q++ = temp; 
	}

	return s; 
}

/* -------------------------------------------------------------------- */
char * itoa(int n, char *s, int radix) {
	if (n>= 0) { 
		return uitoa(n, s, radix); 
	} else { 
		*s = '-'; 
		return uitoa(-(unsigned)n, s + 1, radix) - 1; 
	} 
}

/* -------------------------------------------------------------------- */
char getScanCode() {
	while((inportb(0x64)&0x01)==0) {
		;
	}
	return inportb(0x60);
}



/* -------------------------------------------------------------------- */
WORD16 ScanCode2Ascii(BYTE8 code) {
	if (code == 0xE0 || code == 0xE1) {
		code = getScanCode();
		return 0xE000|code; 	/* ignore */
	}

	if (code & 0x80) 
		return code << 8; 	/* KeyUp */

	if (code >= ENTRIES(scan_ascii))	
		return 0x0000; 		/* ignore */


	if (state.alt)
		return scan_ascii[code][3];

	if (state.ctrl)
		return scan_ascii[code][2];

	if (code >= 0x47) {
		if (state.num) {
			if (state.lshift || state.rshift) {
				return scan_ascii[code][7];
			}
			return scan_ascii[code][4];
		}
	} else if (state.caps) {
		if (state.lshift || state.rshift) {
			return scan_ascii[code][6];
		}
		return scan_ascii[code][5];
	}

	if (state.lshift || state.rshift) {
		return scan_ascii[code][1];
	}

	return scan_ascii[code][0];
}

/* -------------------------------------------------------------------- */
BOOL SetsKybdState(BYTE8 code) {
	switch (code)
		{
		case 0x36: state.rshift = TRUE ; break;
		case 0xB6: state.rshift = FALSE; break;

		case 0x2A: state.lshift = TRUE ; break;
		case 0xAA: state.lshift = FALSE; break;

		case 0x38: state.alt    = TRUE ; break;
		case 0xB8: state.alt	= FALSE; break;

		case 0x1D: state.ctrl	= TRUE ; break;
		case 0x9D: state.ctrl	= FALSE; break;

		case 0x3A: state.caps = !state.caps;
		case 0xBA: break;

		case 0x46: state.scrl = !state.scrl;
		case 0xC6: break;

		case 0x45: state.num  = !state.num;
		case 0xC5: break;

		case 0x52: state.ins  = !state.ins;
		case 0xD2: break;

		default:   return FALSE;
		}

	return TRUE;
}


